﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using Microsoft.Win32;
using System.Diagnostics;
using System.Security.AccessControl;
using System.Security.Cryptography;
using System.Drawing;
using System.Diagnostics;
using IWshRuntimeLibrary;
using System.Web.Script.Serialization;
namespace Setup
{

    public class Logic
    {

#if Test
        public const string AppCode = "10";
#else
        public const string AppCode = "9";
#endif
        public const string ServerBaseAdd = "http://121.36.110.208:8088/api/";
        //public const string ServerBaseAdd = "http://127.0.0.1:8088/api/";
        public static Form1 MainForm { get; set; }

        public static InstallInfo Install { get; set; }

        public static OperationType Type { get; set; }

        public static InstallInfo DefaultInstallInfo()
        {
            string ServerUrl = ServerBaseAdd + "App/" + AppCode;
            HttpResult<AppInfo> appResult = WebLogic.GetHttpResult<AppInfo>(new HttpItem { Url = ServerUrl, Method = HttpMethod.Get });
            if (appResult.Success)
                return appResult.Result.InstallInfo;
            return null;
        }

        public static bool Update()
        {
            InstallInfo info = InstallInfo.Open("setup.xml");
            if (info == null)
                return false;

            string ServerUrl = string.Format("{0}versionmanages/{01}/max", ServerBaseAdd, AppCode);
            HttpResult<ExeVersion> obj = WebLogic.GetHttpResult<ExeVersion>(new HttpItem { Url = ServerUrl, Method = HttpMethod.Get });
            if (!obj.Success)
                return false;

            if (info.DisplayVersion == obj.Result.Num)
                return true;

            ExeVersion version = obj.Result;
            info.DisplayVersion = version.Num;

            //JavaScriptSerializer javaScript = new JavaScriptSerializer();
            //version.Files = javaScript.Deserialize<List<UpdateFile>>(version.FilesJson);
            //info.Files = version.Files.Select<UpdateFile, UpdateFile>(o => new UpdateFile { md5 = o.md5, name = o.name, url = o.url }).ToList();
            //info.Save(AppDomain.CurrentDomain.BaseDirectory + "update.xml");
            //string param = "update.xml" + " update";
            string param = "update";
            System.Diagnostics.Process.Start("Setup.exe", param);
            return false;

        }



    }
    public enum OperationType
    {
        Install = 1,
        Update = 2,
        UnInstall = 3,
    }
    /// <summary>
    /// 注册表操作
    /// </summary>
    public class RegistryLogic
    {
        /// <summary>
        /// 查询程序在本机的完装信息
        /// </summary>
        /// <returns></returns>
        public static InstallInfo GetEexInfo(string softWareKey)
        {

            RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + softWareKey);
            if (key == null)
                return null;
            InstallInfo info = new InstallInfo();
            info.InstallLocation = key.GetValue("InstallLocation")?.ToString();
            info.DisplayName = key.GetValue("DisplayName")?.ToString();
            info.DisplayVersion = key.GetValue("DisplayVersion")?.ToString();
            info.UninstallString = key.GetValue("UninstallString")?.ToString();
            info.Corporation = key.GetValue("Publisher")?.ToString();
            return info;
        }
        /// <summary>
        /// 安装
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public static int Install(InstallInfo info)
        {
            RegistryKey key = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" + info.SoftWareKey, RegistryKeyPermissionCheck.ReadWriteSubTree);
            key.SetValue("InstallLocation", info.InstallLocation);
            key.SetValue("DisplayName", info.DisplayName);
            key.SetValue("DisplayVersion", info.DisplayVersion);
            key.SetValue("UninstallString", info.UninstallString);
            key.SetValue("Publisher", info.Corporation);
            return 1;
        }
        /// <summary>
        /// 卸载
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        public static int UnInstall(InstallInfo info)
        {
            Registry.LocalMachine.DeleteSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + info.SoftWareKey, false);
            return 1;
        }

    }
    public class WebLogic
    {
        public static HttpResult<R> GetHttpResult<R>(HttpItem item)
        {
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            // 准备请求...
            //try
            //{
            // 获取Request
            request = CreateRequest(item);

            using (response = request.GetResponse() as HttpWebResponse)
            {
                return new HttpResult<R>(response);
            }
            //}
            //catch (WebException e)
            //{
            //    if (e.Response != null)
            //    {
            //        response = (HttpWebResponse)e.Response;
            //        HttpResult<R> result = new HttpResult<R>(response);
            //        response.Close();
            //        return result;
            //    }
            //    return new HttpResult<R>(false, null, e.Message);
            //}
        }

        private static HttpWebRequest CreateRequest(HttpItem item)
        {
            HttpWebRequest request = WebRequest.Create(item.Url) as HttpWebRequest;
            request.Method = item.Method.ToString();
            request.ContentType = item.ContentType;
            request.Date = item.Date;
            //request.ra
            if (item.Headers != null)
            {
                foreach (var head in item.Headers)
                {
                    if (head.StartsWith("DATE:"))
                        request.Date = DateTime.Parse(head.Substring(head.IndexOf(":") + 2));
                    else if (head.StartsWith("Content-Type:"))
                        request.ContentType = head.Substring(head.IndexOf(":") + 2);
                    else if (head.StartsWith("Range:"))
                    {
                        string[] spli = head.Split('-');
                        request.AddRange(Convert.ToInt32(spli[0].Remove(0, 13)), Convert.ToInt32(spli[1]));
                    }
                    else
                        request.Headers.Add(head);
                }
            }

            if (item.Content != null && item.Content.Length > 0)
            {
                request.ContentLength = item.Content.Length;
                Stream outstream = request.GetRequestStream();
                outstream.Write(item.Content, 0, item.Content.Length);
                outstream.Close();
            }
            return request;
        }

    }

    /// <summary>
    /// Http请求参数
    /// </summary>
    public class HttpItem
    {
        public HttpItem()
        {
            Headers = new List<string>();
            ContentType = "application/json;charset=UTF-8";
            Headers.Add(string.Format("DATE: {0}", DateTime.UtcNow.ToString("R")));
        }


        /// <summary>
        /// 是否取消当前请求
        /// </summary>
        public bool Cancel
        {
            get;
            set;
        }

        private DateTime date;
        public DateTime Date
        {
            get
            {
                //foreach (var item in Headers)
                //    if (item.StartsWith("DATE:"))
                //        return date;
                //date = DateTime.UtcNow;
                //Headers.Add(string.Format("DATE: {0}", date.ToString("R")));
                return date;
            }
            set
            {
                date = value;
                //Headers.RemoveAll(o => o.StartsWith("DATE:"));
                //Headers.Add(string.Format("DATE: {0}", date.ToString("R")));
            }
        }
        public string Url { get; set; }
        /// <summary>
        /// 请求方法  post,get,put delete等
        /// </summary>
        public HttpMethod Method { get; set; }
        public List<string> Headers { get; set; }

        public Dictionary<string, string> HeadersToDictionary()
        {
            if (Headers.Count == 0)
                return null;
            Dictionary<string, string> dirc = new Dictionary<string, string>();
            foreach (var item in Headers)
            {
                string key = item.Substring(0, item.IndexOf(":"));
                string value = item.Substring(key.Length + 1);
                if (dirc.ContainsKey(key))
                    dirc.Remove(key);
                dirc.Add(key, value);
            }
            return dirc;
        }

        /// <summary>
        /// 如果ContentType赋值,它会覆盖Headers中的conentType
        /// </summary>
        public string ContentType
        {
            get
            {
                foreach (var item in Headers)
                    if (item.StartsWith("Content-Type:"))
                        return item.Substring(item.IndexOf(":") + 2);
                return null;
            }
            set
            {
                Headers.RemoveAll(o => o.StartsWith("DATE:"));
                Headers.Add(string.Format("Content-Type: {0}", value));
            }

        }

        /// <summary>
        /// 请求参数
        /// </summary>
        public object ContentObject { get; set; }


        int _Timeout = 100000;
        /// <summary>
        /// 默认请求超时时间
        /// </summary>
        public int Timeout
        {
            get { return _Timeout; }
            set { _Timeout = value; }
        }
        int _ReadWriteTimeout = 30000;


        /// <summary>
        /// 默认写入Post数据超时间
        /// </summary>
        public int ReadWriteTimeout
        {
            get { return _ReadWriteTimeout; }
            set { _ReadWriteTimeout = value; }
        }


        string _UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)";
        /// <summary>
        /// 客户端访问信息默认Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
        /// </summary>
        public string UserAgent
        {
            get { return _UserAgent; }
            set { _UserAgent = value; }
        }

        CookieCollection cookiecollection = null;
        /// <summary>
        /// Cookie对象集合
        /// </summary>
        public CookieCollection CookieCollection
        {
            get { return cookiecollection; }
            set { cookiecollection = value; }
        }


        string _CerPath = string.Empty;
        /// <summary>
        /// 证书绝对路径
        /// </summary>
        public string CerPath
        {
            get { return _CerPath; }
            set { _CerPath = value; }
        }
        private Boolean isToLower = true;
        /// <summary>
        /// 是否设置为全文小写
        /// </summary>
        public Boolean IsToLower
        {
            get { return isToLower; }
            set { isToLower = value; }
        }
        private Boolean allowautoredirect = true;
        /// <summary>
        /// 支持跳转页面，查询结果将是跳转后的页面
        /// </summary>
        public Boolean Allowautoredirect
        {
            get { return allowautoredirect; }
            set { allowautoredirect = value; }
        }
        private int connectionlimit = 1024;
        /// <summary>
        /// 最大连接数
        /// </summary>
        public int Connectionlimit
        {
            get { return connectionlimit; }
            set { connectionlimit = value; }
        }
        private string proxyusername = string.Empty;
        /// <summary>
        /// 代理Proxy 服务器用户名
        /// </summary>
        public string ProxyUserName
        {
            get { return proxyusername; }
            set { proxyusername = value; }
        }
        private string proxypwd = string.Empty;
        /// <summary>
        /// 代理 服务器密码
        /// </summary>
        public string ProxyPwd
        {
            get { return proxypwd; }
            set { proxypwd = value; }
        }
        private string proxyip = string.Empty;
        /// <summary>
        /// 代理 服务IP
        /// </summary>
        public string ProxyIp
        {
            get { return proxyip; }
            set { proxyip = value; }
        }


        /// <summary>
        /// http body
        /// </summary>
        public byte[] Content { get; set; }

    }

    public enum HttpMethod
    {
        Get = 1,
        Post = 2,
        Put = 3,
        Head = 4,
        Delete = 5
    }

    public class HttpResult<R>
    {
        public int StatusCode { get; set; }
        /// <summary>
        /// 请求是否成功
        /// </summary>
        public bool Success
        {
            get;
            private set;
        }

        /// <summary>
        /// 返回值
        /// </summary>
        public R Result
        {
            get;
            private set;
        }

        /// <summary>
        /// 响应返回的原始值 
        /// </summary>
        public object Content
        {
            get;
            private set;
        }

        /// <summary>
        /// 服务器返回消息
        /// </summary>
        public string Message
        {
            get;
            private set;
        }

        public Dictionary<string, string> Headers
        {
            get;
            private set;
        }


        public HttpResult(bool success, string result, string msg)
        {
            Success = success;
            Message = msg;
            Content = result;
        }

        public HttpResult(HttpWebResponse response)
        {
            if (response == null)
                return;
            Message = response.StatusDescription;
            StatusCode = (int)response.StatusCode;

            if ((int)response.StatusCode >= 200 && (int)response.StatusCode < 300)
                Success = true;

            Headers = new Dictionary<string, string>();
            foreach (var item in response.Headers.AllKeys)
                Headers.Add(item, response.Headers[item]);
            string content = null;
            Stream myResponseStream = response.GetResponseStream();
            byte[] buffer = null;
            if (response.ContentLength > 0)
            {
                buffer = new byte[response.ContentLength];
                int offset = 0;
                int count = 0;
                int length = buffer.Length;
                do
                {
                    count = myResponseStream.Read(buffer, offset, length);
                    offset += count;
                    length -= count;
                } while (count > 0);
                Content = buffer;
                content = System.Text.UTF8Encoding.UTF8.GetString(buffer);
            }
            else
            {
                StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
                content = myStreamReader.ReadToEnd();
                myStreamReader.Close();
                myResponseStream.Close();
                Content = content;
            }

            try
            {
                string typename = typeof(R).Name;
                if (typename == "String")
                {
                    Result = (R)(object)content;
                    return;
                }
                if (typename == "Byte[]" && buffer != null)
                {
                    Result = (R)(object)buffer;
                    return;
                }
                if (!string.IsNullOrEmpty(content))
                {
                    if (typeof(R).IsValueType)
                        Result = (R)Convert.ChangeType(content, typeof(R));
                    else if (response.ContentType.Contains("application/json"))
                    {
                        JavaScriptSerializer javaScript = new JavaScriptSerializer();
                        Result = javaScript.Deserialize<R>(content);
                    }

                }
            }
            catch (Exception)
            {
            }
        }
    }


    public class FileLogic
    {
        /// <summary>
        /// 为文件添加users，everyone用户组的完全控制权限
        /// </summary>
        /// <param name="filePath"></param>
        public static void AddSecurityControll2File(string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            fileInfo.IsReadOnly = false;
            //获得该文件的访问权限
            System.Security.AccessControl.FileSecurity fileSecurity = fileInfo.GetAccessControl();
            //添加ereryone用户组的访问权限规则 完全控制权限
            fileSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow));
            //添加Users用户组的访问权限规则 完全控制权限
            fileSecurity.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow));
            //设置访问权限
            fileInfo.SetAccessControl(fileSecurity);
        }

        public static void AddSecurityControll2DirectoryInfo(string filePath)
        {
            DirectoryInfo info = new DirectoryInfo(filePath);
            //获得该文件的访问权限
            System.Security.AccessControl.DirectorySecurity fileSecurity = info.GetAccessControl();
            //添加ereryone用户组的访问权限规则 完全控制权限
            fileSecurity.AddAccessRule(new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, AccessControlType.Allow));
            //添加Users用户组的访问权限规则 完全控制权限
            fileSecurity.AddAccessRule(new FileSystemAccessRule("Users", FileSystemRights.FullControl, AccessControlType.Allow));
            //设置访问权限
            info.SetAccessControl(fileSecurity);
        }


        public static bool GetWebFileToLocal(string httpUrl, string localPath, Action<int, int> callback = null, bool overwrite = true)
        {
            HttpResult<byte[]> head = WebLogic.GetHttpResult<byte[]>(new HttpItem { Method = HttpMethod.Head, Url = httpUrl });
            if (head.Result == null)
                return false;

            int fileLength = head.Result.Length;
            int count = 2048 * 1024;
            int index = -1;
            int loftindex = count;
            using (FileStream fs = System.IO.File.Create(localPath))
            {
                FileLogic.AddSecurityControll2File(localPath);
                do
                {
                    List<string> hreads = new List<string>();
                    loftindex = (index + count >= fileLength) ? fileLength - 1 : index + count;
                    hreads.Add(string.Format("Range: bytes={0}-{1}", index + 1, loftindex));
                    HttpResult<byte[]> hr = WebLogic.GetHttpResult<byte[]>(new HttpItem { Headers = hreads, Method = HttpMethod.Get, Url = httpUrl });
                    if (hr.Success)
                    {
                        fs.Write(hr.Result, 0, hr.Result.Length);
                        index += count;
                        if (callback != null)
                            callback(index + 1, fileLength);
                    }
                } while (index < fileLength);
            }
            return true;
        }


        public static bool DownloadFile(string url, string dest, Action<Point> collback = null)
        {
            if (!Directory.Exists(Path.GetDirectoryName(dest)))
                Directory.CreateDirectory(Path.GetDirectoryName(dest));

            HttpResult<byte[]> head = WebLogic.GetHttpResult<byte[]>(new HttpItem { Method = HttpMethod.Head, Url = url });
            if (head.Result == null)
            {
                System.IO.File.Create(dest);
                return false;
            }
            int fileLength = head.Result.Length;
            int count = 2048 * 1024;
            int index = -1;
            int loftindex = count;
            using (FileStream fs = System.IO.File.Create(dest))
            {
                FileLogic.AddSecurityControll2File(dest);
                do
                {
                    List<string> hreads = new List<string>();
                    loftindex = (index + count >= fileLength) ? fileLength - 1 : index + count;
                    hreads.Add(string.Format("Range: bytes={0}-{1}", index + 1, loftindex));
                    HttpResult<byte[]> hr = WebLogic.GetHttpResult<byte[]>(new HttpItem { Headers = hreads, Method = HttpMethod.Get, Url = url });
                    if (hr.Success)
                    {
                        fs.Write(hr.Result, 0, hr.Result.Length);
                        index += count;
                        collback?.Invoke(new Point(index + 1, (int)fileLength));
                    }
                } while (index < fileLength);
            }
            return true;
        }

        public static bool Md5Equals(string md5, string fileName)
        {
            if (!string.IsNullOrEmpty(md5) && System.IO.File.Exists(fileName))
            {
                byte[] retVal = null;
                using (FileStream fs = new FileStream(fileName, FileMode.Open))
                {
                    System.Security.Cryptography.MD5 filemd5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
                    retVal = filemd5.ComputeHash(fs);
                }
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                    sb.Append(retVal[i].ToString("x2"));
                return md5 == sb.ToString();
            }
            return false;
        }

    }

    public class ProcessLogic
    {
        public static void CloseProcess(string[] pns, bool closeThis = true)
        {
            int tpid = -1;
            if (!closeThis)
                tpid = System.Diagnostics.Process.GetCurrentProcess().Id;
            Process[] procs = Process.GetProcesses();
            for (int i = 0; i < pns.Length; i++)
            {
                foreach (var item in procs)
                {
                    if (item.ProcessName == pns[i] && item.Id != tpid)
                    {
                        try
                        {
                            item.Kill();
                            System.Threading.Thread.Sleep(1500);
                        }
                        catch (Exception)
                        {

                        }
                    }
                }
            }
        }
    }

    /// <summary>
    /// 防火墙
    /// </summary>
    public class FirewallLogic
    {
        /// <summary>
        /// 添加白名单
        /// </summary>
        /// <returns></returns>
        public static bool FirewallAddRule(string exePath, bool enable)
        {
            try
            {
                ProcessStartInfo cmdext = new ProcessStartInfo("cmd");
                cmdext.UseShellExecute = false;
                cmdext.RedirectStandardInput = true;
                cmdext.RedirectStandardOutput = true;
                cmdext.RedirectStandardError = true;
                cmdext.CreateNoWindow = true;
                cmdext.Verb = "runas";
                System.Diagnostics.Process process = System.Diagnostics.Process.Start(cmdext);

                string cmd = string.Format("netsh advfirewall firewall delete rule name = {0} & netsh advfirewall firewall add rule name={0} dir=in action=allow program={1} enable=yes & exit \n", Path.GetFileName(exePath), exePath);
                process.StandardInput.WriteLine(cmd);
                process.StandardInput.Flush();


                process.WaitForExit(3000);
                string output = process.StandardOutput.ReadToEnd();
                process.Close();
                return true;
            }
            catch (Exception)
            {

            }
            return false;
        }






    }

    public class LinkLogic
    {

        public static void SetLinks()
        {
            InstallInfo info = Logic.Install;
            foreach (var item in info.links)
            {
                if (!SaveLink(item.destination + ".lnk", info.InstallLocation + item.sourceName))
                    MkLink(item.destination, info.InstallLocation + item.sourceName);
            }
        }
        private static bool MkLink(string linkPath, string target)
        {
            try
            {
                string cmd = string.Format("del {0} & mklink {0} {1}  & exit\n", linkPath, target);
                System.Diagnostics.Process p = new System.Diagnostics.Process();
                p.StartInfo.FileName = "cmd.exe";
                p.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                p.StartInfo.RedirectStandardInput = true;//接受来自调用程序的输入信息
                p.StartInfo.RedirectStandardOutput = true;//由调用程序获取输出信息
                p.StartInfo.RedirectStandardError = true;//重定向标准错误输出
                p.StartInfo.CreateNoWindow = true;//不显示程序窗口
                p.Start();//启动程序

                //向cmd窗口发送输入信息
                p.StandardInput.AutoFlush = true;
                p.StandardInput.WriteLine(cmd);

                //p.StandardInput.Flush();
                p.WaitForExit();//等待程序执行完退出进程

                p.Close();
            }
            catch (Exception ex)
            {
                return false;
            }
            return true;
        }

        private static bool SaveLink(string linkPath, string target)
        {
            try
            {
                WshShell shell = new WshShell();
                IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(linkPath);//创建快捷方式对象
                shortcut.TargetPath = target;
                shortcut.WorkingDirectory = Path.GetDirectoryName(target);//设置起始位置
                shortcut.WindowStyle = 1;//设置运行方式，默认为常规窗口
                                         //shortcut.Description = description;//设置备注
                shortcut.IconLocation = target;//设置图标
                shortcut.Save();
            }
            catch
            {
                return false;
            }
            return true;
        }



    }




}

